﻿/* pur @ 定义sock相关调用类的基类
 * date @ 2013.10.22
 * author @ haibin.wang
*/

#ifndef SIMPLESOCK_H
#define SIMPLESOCK_H

#include <string>
/*
 * pur @ 定义sock基类，主要用于server和client的继承共用相关的读写函数和句柄
 * usage @
*/
class SockBase {
    protected:
    int m_fd;          // socket句柄
    std::string m_err; //错误信息

    public:
    SockBase();
    virtual ~SockBase();

    /*
     * pur @ 获取错误信息，当调用CreateConnect出错时再调用此函数可获取错误信息
     * return @ 返回错误信息
    */
    const char *GetErrorInfo();

    /*
     * pur @ 读数据
     * para @ data 存放读取到的数据
     * para @ size 要读取的数据长度
     * para @ timeout 超时时间设置 单位ms, 如果是0则不设置超时时间
     * return @ <0说明错误，否则返回读取到的数据长度, =0 对端关闭连接
    */
    int Read(void *data, int size, int timeout);

    /*
     * pur @ 写数据
     * para @ data 存放读取到的数据
     * para @ size 要读取的数据长度
     * para @ timeout 超时时间设置 单位ms, 如果是0则不设置超时时间
     * return @ <0说明错误，否则返回写的数据长度
    */
    int Write(void *data, int size, int timeout);

    /*
     * pur @ 获取句柄
     * return @ 返回socket句柄
     */
    int GetFd()
    {
        return m_fd;
    }

    /*
     * pur @ 关闭打开的连接句柄
     */
    int closefd();

    protected:
    /*
     * pur @ 超时监测
     * para @ fd 要监测超时的句柄
     * para @ timeout 超时时间设置 单位ms
     * para @ bRead 是否是检测read，true是，false不是
     * return @ false 未超时，true超时
    */
    static bool TimeoutRWCheck(int fd, int timeout, bool bRead = true);
};

/*
 * pur @ socket客户端类
 * usage @  ClientSock mysock;
            mysock.connect(10.1.10.100, 18888, 3000);
            mysock.Read(data, 100, 0);
            mysock.Write(data, 100, 0);
            mysock.CloseConnect();
*/
class ClientSock : public SockBase {
    public:
    ClientSock();
    virtual ~ClientSock();

    /*
     * pur @ 创建连接,使用非阻塞方式创建连接
     * addr @ 连接地址
     * port @ 连接端口
     * timeout @ 超时时间，单位ms, 设置为0则永远等待，
     * return @ 成功返回连接句柄，-1则错误，调用GetErrorInfo获取错误信息
    */
    int CreateConnect(const char *addr, int port, int timeout);

    /*
     * pur @ 关闭连接，
     * return @ 0正常关闭，-1 错误,通过GetErrorInfo获取错误信息
    */
    int CloseConnect();

    private:
    /*
     * pur @ 设置socket为是否为非阻塞
     * para @ fd ，要设置的socket句柄
     * para @ bAsync 是否非阻塞，true为非阻塞，false为阻塞
    */
    int SetAsync(int fd, bool bAsync = true);
};

class ServerSock : public SockBase {
    public:
    ServerSock();
    virtual ~ServerSock();

    /*
     * pur @ 创建server监听socket
     * para @ port 监听的端口
     * return @ 监听sock句柄
     */
    int CreateServer(const int &port);

    /*
     * pur @ 接受连接
     * para @ timeout 接受的超时时间，单位ms
     * para @ addr 获取连接信息，如果不需要则传递NULL
     * return @ 负值错误,否则返回连接描述符
    */
    int Accept(int timeout, struct sockaddr *addr = NULL);
};
#endif
